<template>
  <div class="main-view http-request-view">
    <div class="title">发送HTTP请求</div>
    <el-scrollbar :max-height="getMaxHeight" always>
      <div class="http-request-info">
        <div class="http-request-method">
          <el-select v-model="state.method" style="width: 120px" size="large">
            <el-option value="GET">GET</el-option>
            <el-option value="POST">POST</el-option>
          </el-select>
        </div>
        <div class="http-request-url">
          <el-input v-model="state.url" style="width: 100%" size="large" placeholder="请输入URL地址"></el-input>
        </div>
        <div class="http-request-send">
          <el-button v-if="state.send" type="primary" size="large" @click="onSend">发送</el-button>
          <el-button v-if="state.cancel" type="danger" size="large" @click="onCancel">取消</el-button>
        </div>
      </div>
      <div style="margin-top: 15px; min-height: 300px">
        <el-tabs v-model="state.tab" style="margin-top: 15px">
          <el-tab-pane name="headers" :label="`Headers(${state.headers.length - 1})`">
            <el-table :data="state.headers" max-height="400px">
              <el-table-column prop="date" label="Key" width="360">
                <template #default="sc">
                  <el-input v-model="sc.row.key" @input="onInputChange('headers', sc.$index)"></el-input>
                </template>
              </el-table-column>
              <el-table-column prop="date" label="Value">
                <template #default="sc">
                  <el-input v-model="sc.row.value" @input="onInputChange('headers', sc.$index)"></el-input>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="120">
                <template #default="sc">
                  <el-button v-if="state.headers.length > 1" type="primary" @click="onDeleteRow('headers', sc.$index)"
                    >删除
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
          </el-tab-pane>
          <el-tab-pane name="params" :label="`Params(${state.params.length - 1})`">
            <el-table :data="state.params" max-height="400px">
              <el-table-column prop="date" label="Key" width="360">
                <template #default="scope">
                  <el-input v-model="scope.row.key" @input="onInputChange('params', scope.$index)"></el-input>
                </template>
              </el-table-column>
              <el-table-column prop="date" label="Value">
                <template #default="scope">
                  <el-input v-model="scope.row.value" @input="onInputChange('params', scope.$index)"></el-input>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="120">
                <template #default="scope">
                  <el-button v-if="state.params.length > 1" type="primary" @click="onDeleteRow('params', scope.$index)"
                    >删除
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
          </el-tab-pane>
          <el-tab-pane name="body-json" label="Body-JSON">
            <el-input v-model="state.body.json" type="textarea" :rows="16"></el-input>
          </el-tab-pane>
        </el-tabs>
      </div>
      <div style="margin-top: 15px; min-height: 300px">
        <el-card style="width: 100%">
          <template #header>
            <div class="card-header">
              <span>响应结果({{ state.result_code }})</span>
            </div>
          </template>
          <div v-if="state.result_code === 200">
            {{ state.result }}
          </div>
          <div v-else>
            {{ state.result_msg }}
          </div>
        </el-card>
      </div>
    </el-scrollbar>
  </div>
</template>

<script setup lang="ts">
import { computed, reactive } from 'vue';
import { ElMessage } from 'element-plus';

const state = reactive<{
  tab: 'headers' | 'params' | 'body-json';
  method: string;
  url: string;
  send: boolean;
  cancel: boolean;
  xhr:
    | {
        cancel: () => void;
      }
    | undefined;
  headers: Array<{ key: string; value: string }>;
  params: Array<{ key: string; value: string }>;
  body: {
    json: string;
  };
  result_code: number;
  result_msg: string;
  result: string;
}>({
  tab: 'headers',
  method: 'GET',
  url: '',
  send: true,
  cancel: false,
  xhr: undefined,
  headers: [
    {
      key: '',
      value: ''
    }
  ],
  params: [
    {
      key: '',
      value: ''
    }
  ],
  body: {
    json: ''
  },
  result_code: 0,
  result_msg: '',
  result: ''
});

const getMaxHeight = computed(() => {
  return document.body.offsetHeight - 50;
});

const onInputChange = (type: string, index: number) => {
  if (state[type].length === index + 1) {
    if (state[type][index].key !== '' || state[type][index].value !== '') {
      state[type].push({
        key: '',
        value: ''
      });
    }
  }
  if ('params' === type) {
    if (state.url.indexOf('?') === -1) {
      state.url = state.url + '?';
    }
    const ps: string[] = [];
    for (let i = 0; i < state.params.length; i++) {
      if (state.params[i].key !== '' || state.params[i].value !== '') {
        ps.push(state.params[i].key + '=' + state.params[i].value);
      }
    }
    state.url = state.url.substring(0, state.url.indexOf('?') + 1) + ps.join('&');
  }
};

const onDeleteRow = (type: string, index: number) => {
  if ('headers' === type) {
    state.headers.splice(index, 1);
  }
  if ('params' === type) {
    state.params.splice(index, 1);
  }
};

const onSend = () => {
  if (state.url === '') {
    ElMessage.warning('请添加URL');
    return;
  }
  const headers = {};
  for (const header of state.headers) {
    if (header.key !== '') {
      headers[header.key] = header.value;
    }
  }
  if (state.tab === 'body-json') {
    headers['Content-Type'] = 'application/json';
    headers['Content-Length'] = state.body.json.length;
  }
  state.xhr = window.api.sendHttpRequest(
    state.url,
    {
      method: state.method,
      headers: headers,
      timeout: 5000
    },
    state.body.json,
    (data: { code: number; msg: string; data: string }) => {
      state.result_code = data.code;
      state.result_msg = data.msg;
      state.result = data.data;
      state.send = true;
      state.cancel = false;
    }
  );
  state.send = false;
  state.cancel = true;
};
const onCancel = () => {
  state.xhr?.cancel();
  state.send = true;
  state.cancel = false;
};
</script>

<style scoped lang="scss">
.http-request-view {
  .title {
    height: 50px;
    line-height: 50px;
    margin-bottom: 5px;
    font-size: 18px;
  }

  .http-request-info {
    width: 100%;
    display: flex;
    flex-direction: row;

    .http-request-url {
      flex: 1;
    }
  }
}
</style>
